package com.baiqian.doupo.capability.douqi;

import com.baiqian.doupo.Utils;
import com.baiqian.doupo.douji.DouJi;
import com.baiqian.doupo.douji.DouJi_DouQiShuSong;
import com.baiqian.doupo.douji.DouJi_LingHunGanZhi;
import com.baiqian.doupo.fluids.FluidsRegistry;
import com.baiqian.doupo.gongfa.GongFa;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.Tags;

import java.io.Serializable;
import java.util.ArrayList;

import static com.baiqian.doupo.DouPo.*;
import static com.baiqian.doupo.KeyBoradSave.keyG;

public class DouQiPlayerCapability implements IDouQiCapability, Serializable {

    /**
     * 进阶所已经花费的时间
     * <p>当这个值为0的时候，表示当前已经进阶了0tick
     * <p>当这个值为20的时候，表示当前已经进阶了20tick
     */
    private int level_up_time;
    /**
     * 玩家所拥有的完全压缩后斗气值
     * <p>该值表示的是玩家经过压缩之后的斗气量
     */
    private double douqi_have;
    /**
     * 玩家当前的斗气上限
     * <p>该值并不是进阶用的上限，而是在当前境界中的斗气上限
     */
    private double douqi_have_max;
    /**
     * 玩家当前的境界所能拥有的斗气上限
     * <p>达到该值就开始境界突破
     */
    private double douqi_have_max_level_up;
    /**
     * 当前大境界[0,13]
     * <p>0:凡人
     * <p>1:斗之气
     * <p>2:斗者
     * <p>3:斗师
     * <p>4:大斗师
     * <p>5:斗灵
     * <p>6:斗王
     * <p>7:斗皇
     * <p>8:斗宗
     * <p>9:斗尊
     * <p>10:斗尊巅峰
     * <p>11:半圣
     * <p>12:斗圣
     * <p>13:斗帝
     */
    private byte level_big;
    /**
     * 当前中境界[1,9]
     */
    private byte level_middle;
    /**
     * 当前小境界[1,3]
     */
    private byte level_small;
    /**
     * 当前总境界[小境界，中境界，大境界，总境界]
     * <p>分别统计总共突破了多少个境界，从0开始计数
     */
    private int[] level_all;
    /**
     * 当前斗气的提纯程度
     * <p>当前境界中，斗气的提纯程度，初值是1.0
     */
    private double douqi_compress;
    /**
     * 当前斗气的总提纯程度，是所有境界的斗气的提纯程度的总和
     */
    private double douqi_compress_all;
    /**
     * 理论斗气的总提纯程度，是所有境界的斗气的提纯程度的总和，其从未被压缩过
     */
    private double douqi_compress_should_all;
    /**
     * 斗气提纯的下限，通常为1.0
     */
    private double douqi_min_compress;
    /**
     * 每tick斗气提纯量
     * <p>初始每tick为0.0016</p>
     * <p>每30s1压缩</p>
     */
    private double douqi_compress_attraction;
    /**
     * 每tick斗气吸收量
     * <p>初始每tick为0.00083</p>
     * <p>每分钟1斗气</p>
     */
    private double douqi_attraction;
    /**
     * 晋级时每tick斗气消耗量
     */
    private double douqi_level_up_pay;
    /**
     * 个人输出百分比：当前斗气在最大输出功率百分比内的输出百分比
     * <p>最大输出功率若是50%，个人输出百分比若是10%，则实际输出为5%</p>
     */
    private double douqi_release_percentage;
    /**
     * 最大输出功率，初值30%
     */
    private double douqi_release_percentage_max;
    /**
     * 主灵魂属性
     * <p>0 无§7</p>
     * <p>1 火§e</p>
     * <p>2 风§3</p>
     * <p>3 木§2</p>
     * <p>4 水§9</p>
     * <p>5 冰§b</p>
     * <p>6 土§g</p>
     * <p>7 岩§6</p>
     * <p>8 沙§e</p>
     * <p>9 雷§5</p>
     * <p>10暗§8</p>
     */
    private byte soul_property_main;
    /**
     * 灵魂属性:若有则true，否则false
     * <p>0 无§7</p>
     * <p>1 火§e</p>
     * <p>2 风§3</p>
     * <p>3 木§2</p>
     * <p>4 水§9</p>
     * <p>5 冰§b</p>
     * <p>6 土§g</p>
     * <p>7 岩§6</p>
     * <p>8 沙§e</p>
     * <p>9 雷§5</p>
     * <p>10暗§8</p>
     */
    private boolean[] soul_property;
    /**
     * 灵魂力
     * 代表玩家现在拥有的灵魂力
     */
    private double soul;
    /**
     * 每tick灵魂力回复量
     * <p>玩家灵魂力每tick可以回复多少</p>
     * <p>初始每tick为0.000041666</p>
     * <p>单位1的灵魂力要一天回复完全</p>
     * <p>20分钟(24000tick)是mc的一天</p>
     */
    private double soul_attraction_num;
    /**
     * 灵魂力上限
     */
    private double soul_max;
    /**
     * 异火:有则ture，否则false
     */
    private boolean[] fire;
    /**
     * 体质
     * <p>0:普通</p>
     * <p>1.厄难毒体</p>
     */
    private byte body;
    /**
     * 眼睛
     * <p>0:普通</p>
     * <p>1.碧蛇三花瞳</p>
     */
    private byte eye;
    /**
     * 是否正在进大阶
     */
    private boolean is_to_level_big;
    /**
     * 是否正在进中阶
     */
    private boolean is_to_level_middle;
    /**
     * 是否正在进小阶
     */
    private boolean is_to_level_small;
    /**
     * 是否已经展开斗气化翼
     */
    private boolean isFlying;
    /**
     * 当前环境中各属性的浓度
     * <p>0 无§7</p>
     * <p>1 火§e</p>
     * <p>2 风§3</p>
     * <p>3 木§2</p>
     * <p>4 水§9</p>
     * <p>5 冰§b</p>
     * <p>6 土§g</p>
     * <p>7 岩§6</p>
     * <p>8 沙§e</p>
     * <p>9 雷§5</p>
     * <p>10暗§8</p>
     */
    private double[] world_attr;
    /**
     * 线程计算的周围半径中方块提供给环境的各属性的浓度
     * <p>提供给world_attr使用</p>
     */
    private double[] world_attr_from_block_th;
    /**
     * 是否正在扫描方块
     * <p>让扫描线程不会短时间内反复启动</p>
     */
    private boolean is_scaning_block;

    /**
     * 所拥有的的功法
     */
    private ArrayList<GongFa> gongfas;
    /**
     * 选择的功法
     */
    private int gongfa_choose;
    /**
     * 所拥有的的斗技
     */
    private ArrayList<DouJi> doujis;
    /**
     * 选了的是第几组斗技[0,3]
     */
    private int douji_group_choose;
    /**
     * 共16格，4组斗技[0,15]
     * <p>-1代表没有选择斗技</p>
     */
    private int[] douji_group;

    /**
     * 1点斗气能提供多少攻击力
     * <p>属性将会影响该值</p>
     */
    private double attack_num;
    /**
     * 1点斗气能提供多少防御力
     * <p>属性将会影响该值</p>
     */
    private double defense_num;
    /**
     * 1点斗气能提供多少治愈力
     * <p>属性将会影响该值</p>
     */
    private double recover_num;

    public DouQiPlayerCapability() {
        rebirth();
    }

    /**
     * 玩家数据更新函数
     * <p>当版本更新导致nbt数据有所增删改，那么应该调整DouPo类里面的VERSION</p>
     * <p>且在该函数中为旧版本玩家提供数据修正</p>
     *
     * @param player_version nbt中玩家数据所处的版本
     */
    private void playerUpdate(int player_version) {
//        if(player_version<2) {//1号版本的更新
//            boolean flag = true;
//            for (DouJi douji : getDouJis())
//                if (douji.douji_name.equals("斗气输送")) {
//                    flag = false;
//                    break;
//                }
//            if(flag)
//                addDouJi(new DouJi_DouQiShuSong());
//            flag = true;
//            for (DouJi douji : getDouJis())
//                if (douji.douji_name.equals("灵魂感知")) {
//                    flag = false;
//                    break;
//                }
//            if(flag)
//                addDouJi(new DouJi_HuoDing());
//        }
    }

    /**
     * 生成人物所有灵魂属性和主属性
     */
    private boolean[] createSoulProperty() {
        boolean[] soul_property = new boolean[SOUL_MAX];
        byte i, j;
        int num;
        //初始化：无灵魂属性
        for (i = 0; i < SOUL_MAX; ++i)
            soul_property[i] = false;
        //出生最多自带三属性
        num = (int) (Math.random() * 100);//[0,99]
        if (num < 90) {//90%一个属性
            num = 1;
        } else if (num < 97) {//7%两个属性
            num = 2;
        } else {//3%三个属性
            num = 3;
        }
        //生成灵魂属性
        i = 0;
        while (i < num) {
            j = (byte) ((byte) (Math.random() * (SOUL_MAX - 1)) + 1);//最大属性数量
            //若可以增加该灵魂属性，则增加
            if (!soul_property[j]) {
                soul_property[j] = true;
                //第一个属性就是灵魂主属性
                if (i == 0)
                    soul_property_main = j;
                ++i;
            }
        }
        return soul_property;
    }

    /**
     * 生成人物灵魂强度
     */
    private double createSoulMax() {
        double num = Math.random() * 100;
        int soul_num = 0;
        for (int i = 0; i < SOUL_MAX; ++i)
            if (soul_property[i])
                ++soul_num;
        //灵魂属性数量将影响灵魂强度
        if (num < 88 - (soul_num - 1) * 5) {//88%的几率是个正常人
            num = 1 + (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 3);
        } else if (num < 93) {//5%的几率是残废
            num = 0.4 + (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 3);
        } else if (num < 98 - (soul_num - 1)) {//5%两倍灵魂
            num = 2 + (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 2);
        } else {//2%三倍灵魂
            num = 2.75 + (Math.random() < 0.5 ? -1 : 1) * (Math.random() / 4);
        }
        return num;
    }

    /**
     * 生成人物体质
     */
    private byte createBody() {
        double num = Math.random();
        if (num < 0.01) {//1%
            return 1;//返回厄难毒体
        } else {
            return 0;//普通体质
        }
    }

    /**
     * 生成人物眼睛
     */
    private byte createEye() {
        double num = Math.random();
        if (num < 0.01) {//1%
            return 1;//返回碧蛇三花瞳
        } else {
            return 0;//普通体质
        }
    }

    /**
     * 生成斗气带来的对攻击，防御和治愈的数值修正
     */
    private void createNum() {
        //总1.2
        switch (soul_property_main) {
            case 1: {
                attack_num = 0.7;
                defense_num = 0.3;
                recover_num = 0.2;
                break;
            }
            case 2: {
                attack_num = 0.5;
                defense_num = 0.4;
                recover_num = 0.3;
                break;
            }
            case 3: {
                attack_num = 0.2;
                defense_num = 0.3;
                recover_num = 0.7;
                break;
            }
            case 4: {
                attack_num = 0.3;
                defense_num = 0.4;
                recover_num = 0.5;
                break;
            }
            case 5: {
                attack_num = 0.5;
                defense_num = 0.5;
                recover_num = 0.2;
                break;
            }
            case 6: {
                attack_num = 0.3;
                defense_num = 0.5;
                recover_num = 0.4;
                break;
            }
            case 7: {
                attack_num = 0.4;
                defense_num = 0.7;
                recover_num = 0.1;
                break;
            }
            case 8: {
                attack_num = 0.5;
                defense_num = 0.4;
                recover_num = 0.3;
                break;
            }
            case 9: {
                attack_num = 0.8;
                defense_num = 0.3;
                recover_num = 0.1;
                break;
            }
            case 10: {
                attack_num = 0.4;
                defense_num = 0.4;
                recover_num = 0.4;
                break;
            }
            default: {
                attack_num = 0.5;
                defense_num = 0.5;
                recover_num = 0.5;
                break;
            }
        }
    }

    //=======================================================
    @Override
    public void rebirth() {
        level_up_time = 0;//默认没有在升级
        douqi_have = 0.0;//初始斗气0
        douqi_have_max = 0.0;//初始斗气上限0
        douqi_have_max_level_up = 1.0;//凡人向斗者进阶需要积累1斗气
        level_big = 0;//无大境界
        level_middle = 0;//无中境界
        level_small = 0;//无小境界
        level_all = new int[]{0, 0, 0, 0};//所有境界均无突破记录
        douqi_compress = 1.0;//提纯程度为1
        douqi_compress_all = 1.0;//总提纯程度为1
        douqi_compress_should_all = 1.0;//总应提纯程度为1
        douqi_min_compress = 1.0;
        douqi_compress_attraction = 0.0016;//每30s压缩1
        douqi_attraction = 0.00083;//每分钟聚集1斗气
        douqi_release_percentage = 1.0;//默认个人输出功率100%
        douqi_release_percentage_max = 0.3;//默认最大输出功率30%
        soul_property = createSoulProperty();//生成人物所有属性以及选取主属性
        soul_max = createSoulMax();//生成灵魂最大强度
        soul = soul_max;//初始化灵魂力
        soul_attraction_num = 0.000041666;//每天回复1个灵魂
        fire = new boolean[FIRE_MAX];
        for (int i = 0; i < FIRE_MAX; ++i)//无异火
            fire[i] = false;
        body = createBody();
        eye = createEye();
        is_to_level_big = false;
        is_to_level_middle = false;
        is_to_level_small = false;
        isFlying = false;
        world_attr = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
        world_attr_from_block_th = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
        is_scaning_block = false;
        gongfas = new ArrayList<>();
        doujis = new ArrayList<>();
        gongfa_choose = -1;//没有选择功法
        douji_group = new int[16];
        for (int i = 0; i < 16; ++i) {
            douji_group[i] = -1;//都没有选择斗技
        }
        douji_group_choose = 0;//选择了第一组
        createNum();
    }

    @Override
    public void tryToUpLevel(PlayerEntity player_entity) {//试图升级
        if (level_big == 13 && level_middle == 9) {//巅峰斗帝不用升级
            return;
        }
        if (douqi_have >= douqi_have_max_level_up) {//如果满溢斗气
            if (!(is_to_level_big || is_to_level_middle || is_to_level_small)) {//如果没在进阶，那就开始进阶
                switch (level_big) {
                    case 0://凡人进阶
                        addDouQiLevel(player_entity);
                        addDouJi(new DouJi_DouQiShuSong());
                        addDouJi(new DouJi_LingHunGanZhi());
                        player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".have_dou_qi"), player_entity.getUniqueID());
                        break;
                    case 10:
                    case 9:
                    case 8:
                    case 7:
                    case 6:
                    case 5:
                    case 4:
                    case 3:
                    case 2:
                    case 1:
                    case 13://斗帝就算是进阶大境界吧
                        if (level_middle == 9) {//进阶大境界
                            is_to_level_big = true;
                            switch (level_big) {
                                case 1:
                                    player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_2_begin"), player_entity.getUniqueID());
                                    break;
                                default:
                                    player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                                    break;
                            }
                        } else {//进阶中境界
                            is_to_level_middle = true;
                            player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                        }
                        break;
                    case 11:
                        if (level_small == 3) {//进阶大境界
                            is_to_level_big = true;
                            player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                        } else {
                            is_to_level_small = true;//进阶小境界
                            player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                        }
                        break;
                    case 12:
                        if (level_small == 3) {//进阶
                            if (level_middle == 9) {//进阶大境界
                                is_to_level_big = true;
                                player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                            } else {
                                is_to_level_middle = true;//进阶中境界
                                player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                            }
                        } else {
                            is_to_level_small = true;//进阶小境界
                            player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_begin"), player_entity.getUniqueID());
                        }
                        break;
                }
            }
        }
    }

    @Override
    public String getDouQiLevelStr() {
        String big = new TranslationTextComponent("gui." + Utils.MOD_ID + ".level_big_" + level_big).getString();
        String middle = "";
        String small = "";
        switch (level_big) {
            case 1:
                middle = new TranslationTextComponent("gui." + Utils.MOD_ID + ".level_middle_1_" + level_middle).getString();
                break;
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
            case 9:
            case 11:
                if (level_big == 11) {
                    small = new TranslationTextComponent("gui." + Utils.MOD_ID + ".level_small_1_" + level_small).getString();
                    break;
                }
            case 12:
                if (level_big == 12)
                    small = new TranslationTextComponent("gui." + Utils.MOD_ID + ".level_small_2_" + level_small).getString();
            case 13:
                middle = new TranslationTextComponent("gui." + Utils.MOD_ID + ".level_middle_2_" + level_middle).getString();
                break;
            case 10:
                middle = new TranslationTextComponent("gui." + Utils.MOD_ID + ".level_middle_3_" + level_middle).getString();
                break;
        }
        return small + middle + big;
    }

    @Override
    public double getBaseDamage() {
        //斗帝伤害最高10万
        /*
         e^G=100000
         G=ln(100000)=54*x+117*y+13*z=11.512925464970228420089957273422
                    2      3    5
         */
        return Math.pow(Math.E, (
                level_all[0] * 0.04264046468507492007440724916082 +
                        level_all[1] * 0.02952032170505186774382040326518 +
                        level_all[2] * 0.44280482557577801615730604897777));
    }

    @Override
    public double getBaseDefense() {
        //斗帝防御最高10万
        /*
         e^G=100000
         G=ln(100000)=54*x+117*y+13*z=11.512925464970228420089957273422
                    2      3    5
         */
        return Math.pow(Math.E, (
                level_all[0] * 0.04264046468507492007440724916082 +
                        level_all[1] * 0.02952032170505186774382040326518 +
                        level_all[2] * 0.44280482557577801615730604897777));
    }

    @Override
    public double getMaxDouQiPay() {
        //拥有的斗气
        double douqi_pay = getDouQi(0);
        //最大能输出的斗气
        double douqi_need_pay = getDouQiHaveMax() * getExDouQiReleasePercentage() * getExCompressAll();
        if (douqi_pay > douqi_need_pay) {
            douqi_pay = douqi_need_pay;
        }
        return douqi_pay;
    }

    @Override
    public double getDamage() {
        double damage = getBaseDamage();
        damage += attack_num * getMaxDouQiPay();
        if (gongfa_choose != -1)
            damage += gongfas.get(gongfa_choose).gongfa_attack_num;
        for (int i = 0; i < 4; ++i) {
            if (douji_group[douji_group_choose * 4 + i] != -1) {//如果斗技存在
                DouJi douji = doujis.get(douji_group[douji_group_choose * 4 + i]);
                if (douji.use_time > 0 || douji.use_time == -1) {//且正在使用
                    if (douji.douji_type == 3)//还是个附加攻击型
                        damage += douji.douji_attack_num;
                }
            }
        }
        return damage;
    }

    @Override
    public double getDefense() {
        double defense = getBaseDefense();
        defense += defense_num * getMaxDouQiPay();
        if (gongfa_choose != -1)
            defense += gongfas.get(gongfa_choose).gongfa_defense_num;
        for (int i = 0; i < 4; ++i) {
            if (douji_group[douji_group_choose * 4 + i] != -1) {//如果斗技存在
                DouJi douji = doujis.get(douji_group[douji_group_choose * 4 + i]);
                if (douji.use_time > 0 || douji.use_time == -1) {//且正在使用
                    if (douji.douji_type == 4)//还是个附加防御型
                        defense += douji.douji_defense_num;
                }
            }
        }
        return defense;
    }

    @Override
    public double getSoulPercentage() {
        return soul / soul_max;
    }

    @Override
    public boolean isGettingDouQi(PlayerEntity player_entity) {
        if (keyG.get(player_entity.getUniqueID()) > 0)
            return true;
        return false;
    }

    @Override
    public TranslationTextComponent getBodyName() {
        return new TranslationTextComponent("gui." + Utils.MOD_ID + ".body_" + body);
    }

    @Override
    public TranslationTextComponent getEyeName() {
        return new TranslationTextComponent("gui." + Utils.MOD_ID + ".eye_" + eye);
    }

    @Override
    public void addDouQiLevel(PlayerEntity player_entity) {//斗气境界升级
        double douqi_temp = getDouQi(0);//完全解压
        douqi_compress_all += douqi_compress;//将当前境界所拥有的浓缩值累积到总浓缩值上
        ++douqi_compress_should_all;//将该境界下基本的总浓缩度+1
        ++level_all[3];
        douqi_min_compress = 1.0;//下限回归1.0
        douqi_compress = douqi_min_compress;//浓缩率归1

        //调整level
        switch (level_big) {//根据大境界来判断下个应该升什么境界
            case 0://凡人升斗者
                ++level_big;
                ++level_all[2];
                level_middle = 1;
                level_small = 0;
                break;
            case 9:
            case 8:
            case 7:
            case 6:
            case 5:
            case 4:
            case 3:
            case 2:
            case 1:
                if (level_middle == 9) {//如果要晋级大境界
                    ++level_big;
                    ++level_all[2];
                    level_middle = 1;
                    level_small = 0;
                } else {//否则，则是晋级中境界
                    ++level_middle;
                    ++level_all[1];
                }
                break;
            case 10:
                if (level_middle == 9) {
                    ++level_big;
                    ++level_all[2];
                    //晋升为半圣，斗气换态
                    level_middle = 0;
                    level_small = 1;
                } else {
                    ++level_middle;
                    ++level_all[1];
                }
                break;
            case 11:
                if (level_small == 3) {
                    ++level_big;
                    level_small = 1;
                    level_middle = 1;
                } else {
                    ++level_small;
                    ++level_all[0];
                }
                break;
            case 12:
                if (level_small == 3) {
                    level_small = 1;
                    if (level_middle == 9) {
                        level_middle = 1;
                        level_small = 0;
                        ++level_big;
                        //晋升为斗帝，斗气换态
                    } else {
                        ++level_middle;
                        ++level_all[1];
                    }
                } else {
                    ++level_small;
                    ++level_all[0];
                }
                break;
            case 13:
                if (level_middle == 9) {//不变
                    //此时已经是斗帝最终形态，不会再有变化
                } else {
                    ++level_middle;
                    ++level_all[1];
                }
        }

        //灵魂增长率，斗气增长率，斗气上限增长
        //凡人每分钟回复1/20人的灵魂,最高200人份灵魂
        //经计算，斗帝将每分钟回复约10人份的灵魂,凡人到斗帝需要提升200倍的回复速度
        /*
         e^G=200
         G=ln(200)=54*x+117*y+13*z=5.2983173665480366774532150308269
                    2      3    5
         */
        soul_attraction_num = 0.000041666 * Math.pow(Math.E, (
                level_all[0] * 0.01962339765388161732390079641047 +
                        level_all[1] * 0.01358542914499496583962362828417 +
                        level_all[2] * 0.20378143717492448759435442426257));
        //凡人每分钟回1斗气
        //经计算，斗帝将每分钟回复6亿斗气
            /*
         e^G=200
         G=ln(600000000)=54*x+117*y+13*z=20.212440213180420472956408995856
                      2      3    5
             * */
        douqi_attraction = 0.00083 * Math.pow(Math.E, (
                level_all[0] * 0.07486088967844600175169040368836 +
                        level_all[1] * 0.05182676977738569352040104870732 +
                        level_all[2] * 0.77740154666078540280601573060985));
        //斗之气1斗气
        //斗帝有1000亿的斗气
        /*
         e^G=100000000000
         G=ln(100000000000)=54*x+117*y+13*z=25.328436022934502524197906001528
                              2      3    5
         * */
        douqi_have_max_level_up = Math.pow(Math.E, (
                level_all[0] * 0.09380902230716482416369594815381 +
                        level_all[1] * 0.06494470775111410903640488718341 +
                        level_all[2] * 0.97417061626671163554607330775108));

        /*晋级消耗斗气设置
         e^G=2.9
         G=ln(2.9)=54*x+117*y+13*z=1.0647107369924283431652805776775
                              2      3    5
                              基本：消耗1个灵魂的人的1倍压缩
                              增加：对灵魂和压缩逐渐有要求
                              最终：消耗1人份灵魂的人的3倍率压缩
         * */
//        soul_need*=Math.pow(Math.E,(
//                level_all[0]*0.00852809293701498401488144983216+
//                        level_all[1]*0.00590406434101037354876408065304+
//                        level_all[2]*0.08856096511515560323146120979555));
        double compress_need = 0.1 + Math.pow(Math.E, (//目前的消耗模拟对象的倍率
                level_all[0] * 0.00394337309997195682653807621362 +
                        level_all[1] * 0.00273002753074981626452636045558 +
                        level_all[2] * 0.04095041296124724396789540683375));

        compress_need += Math.pow(compress_need, level_all[3]);//得到完全压缩程度
        douqi_level_up_pay = douqi_have_max_level_up * (compress_need / douqi_compress_all);//完全压缩
        douqi_level_up_pay /= 23 * 20;//分23秒消耗完毕

        setDouQi(douqi_temp, 0, player_entity);
    }

    @Override
    public void updateWorldAttr(PlayerEntity player, World world) {
        for (int i = 0; i < world_attr.length; ++i) {
            world_attr[i] = 0;
        }
        int px = (int) player.getPosX();
        int py = (int) player.getPosY();//获取人物高度
        int pz = (int) player.getPosZ();
        if (py > 256) {
            world_attr[2] += 256 * 0.003;
        } else {
            world_attr[2] += (py - 80) * 0.003;//风属性加强
            if (world_attr[2] < 0)
                world_attr[2] = 0;
        }
        //人物是否入水
        if (player.isInWater()) {
            world_attr[4] += 0.02;
            world_attr[5] += 0.008;
            world_attr[1] -= 0.02;
        }

        //根据亮度增加浓度
        world_attr[10] -= (player.world.getLight(new BlockPos(px, py, pz)) - 7) * 0.002;

        //获取群系
        switch (player.world.getBiome(new BlockPos(px, py, pz)).getCategory().getName()) {
            case ("none"):
                world_attr[0] += 0.1;
                world_attr[10] += 0.1;
                break;//无
            case ("taiga"):
                world_attr[3] += 0.08;
                world_attr[6] += 0.03;
                break;//针叶林
            case ("extreme_hills"):
                world_attr[6] += 0.02;
                world_attr[7] += 0.1;
                world_attr[8] += 0.01;
                break;//峭壁/山地
            case ("jungle"):
                world_attr[3] += 1.2;
                world_attr[4] += 0.02;
                world_attr[6] += 0.02;
                break;//丛林
            case ("mesa"):
                world_attr[1] += 0.02;
                world_attr[4] += 0.01;
                world_attr[6] += 0.03;
                break;//平顶山/粘土平原
            case ("plains"):
                world_attr[6] += 0.02;
                break;//平原
            case ("savanna"):
                world_attr[6] += 0.03;
                break;//热带草原
            case ("icy"):
                world_attr[4] += 0.05;
                world_attr[5] += 0.1;
                world_attr[1] -= 0.07;
                break;//冰山？
            case ("the_end"):
                world_attr[0] += 0.05;
                world_attr[10] += 0.1;
                break;//末地
            case ("beach"):
                world_attr[2] += 0.01;
                world_attr[4] += 0.03;
                world_attr[8] += 0.08;
                break;//沙滩
            case ("forest"):
                world_attr[3] += 0.1;
                world_attr[6] += 0.03;
                break;//森林
            case ("ocean"):
                world_attr[4] += 1.5;
                world_attr[1] -= 0.07;
                break;//海洋
            case ("desert"):
                world_attr[1] += 0.05;
                world_attr[8] += 0.1;
                world_attr[4] -= 1.7;
                break;//沙漠
            case ("river"):
                world_attr[4] += 0.03;
                world_attr[1] -= 0.03;
                break;//河流
            case ("swamp"):
                world_attr[3] += 0.03;
                world_attr[4] += 0.05;
                world_attr[6] += 0.05;
                world_attr[10] += 0.02;
                world_attr[1] -= 0.01;
                break;//沼泽
            case ("mushroom"):
                world_attr[6] += 0.02;
                world_attr[10] += 0.05;
                break;//蘑菇岛
            case ("nether"):
                world_attr[1] += 0.1;
                world_attr[10] += 0.07;
                break;//下界
            default:
                break;
        }
        //获取天气
        if (player.world.isRaining()) {
            world_attr[4] += 0.03;
            world_attr[1] -= 0.07;
            if (player.world.isThundering()) {
                world_attr[2] += 0.04;
                world_attr[4] += 0.08;
                world_attr[9] += 0.1;
                world_attr[10] += 0.03;
                world_attr[1] -= 0.1;
            }
        }
        if (player.world.isDaytime()) {
            world_attr[1] += 0.005;
        } else {
            world_attr[10] += 0.02;
        }

        //扫描人物周遭方块类型
        if (!is_scaning_block) {
            is_scaning_block = true;
            new Scan_Thread(player, world).start();
        }
        for (int i = 0; i < SOUL_MAX; ++i)
            world_attr[i] += world_attr_from_block_th[i];
    }

    @Override
    public double getLevelUpPay() {
        return douqi_level_up_pay;
    }

    @Override
    public void addLevelUpTime(int num) {
        num = level_up_time + num;
        if (num < 0)
            level_up_time = 0;
        else
            level_up_time = num;
    }

    //=======================================================

    @Override
    public int getLevelUpTime() {
        return level_up_time;
    }

    @Override
    public void setLevelUpTime(int num) {
        if (num < 0)
            level_up_time = 0;
        else
            level_up_time = num;
    }

    @Override
    public int getLevelUpTimeMax() {
        if (is_to_level_big)
            return 20 * 30;
        else if (is_to_level_middle)
            return 20 * 20;
        else
            return 20 * 15;
    }

    @Override
    public void addDouQi(PlayerEntity player_entity) {
        addDouQi(douqi_attraction, 0, true, player_entity);
    }

    @Override
    public void addDouQi(double num, int level, boolean is_be_affect, PlayerEntity player_entity) {
        //根据灵魂属性计算受环境影响的斗气增减
        double world_add = 1.0;//受环境影响的增幅倍率
        if (is_be_affect) {
            for (int i = 0; i < SOUL_MAX; ++i)
                if (soul_property[i])
                    world_add += world_attr[i];
            //主属性的额外增长
            world_add += world_attr[soul_property_main] * 0.3;
        }
        //斗气增长量：每秒斗气吸收量*环境增加速率*灵魂力*/完全压缩程度[*功法额外提供斗气增长速率]
        // 环境影响：环境影响:增加斗气吸收量||减少斗气消耗量
        num = num > 0 ? (num * world_add) : (num / world_add);
        if (is_be_affect) {
            // 环境影响：灵魂力
            num = num > 0 ? (num * soul) : (num / soul);
            //受功法影响
            if (gongfa_choose != -1)
                num = num > 0 ? (num * gongfas.get(gongfa_choose).gongfa_douqi_speed) : (num / gongfas.get(gongfa_choose).gongfa_douqi_speed);
        }
        switch (level) {
            case 1:
            case 3: {
                //直接的增减
                break;
            }
            case 2: {
                //将新加入的未压缩的斗气进行此境界的压缩，消耗的时候则进行此境界的解压
                num = num / douqi_compress;
                break;
            }
            default: {
                //将新加入的未压缩的斗气进行完全压缩，消耗的时候则完全解压
                num = num / getExCompressAll();
            }
        }
        num += douqi_have;//此时num代表变化后的斗气
        if (num > douqi_have_max) {//如果斗气增长后的总量大于修炼用斗气上限的话，就试图提高上限
            if (num > douqi_have_max_level_up) {//如果要提升的斗气大于等级上限斗气，则不再提高上限，并将多余斗气散失
                douqi_have_max = douqi_have_max_level_up;
                num = douqi_have_max_level_up;
            } else {//否则提高上限
                douqi_have_max += (num - douqi_have_max) * 0.6;//超过的部分要剪掉0.4才算入增长
            }
        } else if (num < 0) {
            num = 0.0;
            if (is_to_level_big && is_to_level_middle && is_to_level_small) {
                //晋升失败
                if (douqi_min_compress >= 1.5)
                    douqi_min_compress = 1.5;
                else
                    //晋升失败将导致斗气下限上升1%
                    douqi_min_compress *= 1.01;
                if (is_to_level_big) {
                    switch (level_big) {
                        case 1:
                            player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_2_end_bad"), player_entity.getUniqueID());
                            break;
                        default:
                            player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_end_bad"), player_entity.getUniqueID());
                            break;
                    }
                } else if (is_to_level_middle) {
                    player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_end_bad"), player_entity.getUniqueID());
                } else if (is_to_level_small) {
                    player_entity.sendMessage(new TranslationTextComponent("message." + Utils.MOD_ID + ".to_level_default_end_bad"), player_entity.getUniqueID());
                }
                is_to_level_big = false;
                is_to_level_middle = false;
                is_to_level_small = false;
                level_up_time = 0;
            }
        }
        douqi_have = num;
        tryToUpLevel(player_entity);//变化斗气后尝试升级
    }

    @Override
    public void setDouQi(double num, int level, PlayerEntity player_entity) {
        if (num < 0.0)//设置的斗气值不应该是负数
            return;
        switch (level) {
            case 1:
            case 3: {
                if (num > douqi_have_max) {
                    if (num > douqi_have_max_level_up) {//如果要提升的斗气大于等级上限斗气，则不再提高上限，并将多余斗气散失
                        douqi_have_max = douqi_have_max_level_up;
                        num = douqi_have_max_level_up;
                    } else {//否则提高上限
                        douqi_have_max = num;
                    }
                }
                douqi_have = num;
                break;
            }
            case 2: {
                douqi_have = num / douqi_compress;
                break;
            }
            default: {
                douqi_have = num / getExCompressAll();
            }
        }
        tryToUpLevel(player_entity);//斗气值变化后应该试图升级
    }

    @Override
    public double getDouQi(int level) {
        switch (level) {
            case 1:
            case 3: {
                return douqi_have;
            }
            case 2: {
                return douqi_have * douqi_compress;
            }
            default: {
                return douqi_have * getExCompressAll();
            }
        }
    }

    @Override
    public void setDouQiHaveMax(double num, PlayerEntity player_entity) {
        if (num < 0.0)//设置的值不应该是负数
            return;
        else if (num > douqi_have_max_level_up)//设置的斗气值不应该超过斗气上限值
            num = douqi_have_max_level_up;
        douqi_have_max = num;
        tryToUpLevel(player_entity);
    }

    @Override
    public double getDouQiHaveMax() {//获取修炼提升等级用斗气上限值
        return douqi_have_max;
    }

    @Override
    public double getDouQiHaveMaxLevelUp() {//该修炼等级的斗气上限值,突破该值即升级
        return douqi_have_max_level_up;
    }

    @Override
    public int getLevelBig() {
        return level_big;
    }

    @Override
    public int getLevelMiddel() {
        return level_middle;
    }

    @Override
    public int getLevelSmall() {
        return level_small;
    }

    @Override
    public int[] getLevelAll() {
        return level_all;
    }

    @Override
    public void addDouQiCompress(PlayerEntity player_entity) {
        addDouQiCompress(douqi_compress_attraction, true, player_entity);
    }

    @Override
    public void loseDouQiCompress(PlayerEntity player_entity) {
        if (douqi_compress > douqi_min_compress)
            addDouQiCompress(-douqi_compress_attraction, true, player_entity);
        else if (douqi_compress < douqi_min_compress) {
            double douqi_have_temp = getDouQi(0);//完全解压的斗气
            douqi_compress = douqi_min_compress;
            setDouQi(douqi_have_temp, 0, player_entity);
        }
    }

    @Override
    public void addDouQiCompress(double num, boolean is_be_affect, PlayerEntity player_entity) {//增长斗气浓缩率
        double douqi_have_temp = getDouQi(0);//完全解压的斗气
        //斗气浓缩增长率：每tick斗气提纯量 *灵魂力 *0.75/完全压缩程度[*功法额外提供斗气浓缩速率]
        if (is_be_affect) {
            //受灵魂影响
            num = num > 0 ? (num * soul * 0.75) : (num / soul);
            //受压缩程度影响
            num = num > 0 ? (num / (getCompressAttractioinDiff() * douqi_compress)) : (num * (getCompressAttractioinDiff() * douqi_compress / 2));
            if (gongfa_choose != -1)
                num = num > 0 ? (num * gongfas.get(gongfa_choose).gongfa_compress_speed) : (num / gongfas.get(gongfa_choose).gongfa_compress_speed);
        }
        if (num < 0)
            num *= 0.3;//衰落速度为0.3
        num = douqi_compress + num;//变化后的斗气浓缩率
        if (num <= 0)
            num = 0.00001;
        douqi_compress = num;
        setDouQi(douqi_have_temp, 0, player_entity);
    }

    @Override
    public void setDouQiCompress(double num, PlayerEntity player_entity) {
        if (num <= 0.0)
            return;
        //重新压缩
        douqi_have = douqi_have * douqi_compress / num;
        douqi_compress = num;
        tryToUpLevel(player_entity);
    }

    @Override
    public double getDouQiCompress() {
        return douqi_compress;
    }

    @Override
    public double getExCompressAll() {
        return douqi_compress * (douqi_compress_all - douqi_compress_should_all + 1);
    }

    @Override
    public double getCompressAll() {
        return douqi_compress_all;
    }

    @Override
    public double getCompressShouldAll() {
        return douqi_compress_should_all;
    }

    @Override
    public double getCompressAttractioinDiff() {

       /*斗气压缩难度设置:
       [1,5]对应难度[1,2.2]
        */
        ;
        if (level_all[3] == 0)
            return 1;
        return ((douqi_compress_all - 1) / level_all[3] - 1) * 1.2 / 4 + 1;
    }

    @Override
    public double getCompressAttractioin() {
        return douqi_compress_attraction;
    }

    @Override
    public double getDouQiAttraction() {
        return douqi_attraction;
    }

    @Override
    public double getDouQiLevelUpPay() {
        return douqi_level_up_pay;
    }

    @Override
    public double getExDouQiReleasePercentage() {
        return douqi_release_percentage * douqi_release_percentage_max;
    }

    @Override
    public void addDouQiReleasePercentage() {
        if (douqi_release_percentage == 1.0)
            return;
        douqi_release_percentage += 0.01;
        if (douqi_release_percentage > 1.0)
            douqi_release_percentage = 1.0;
    }

    @Override
    public void loseDouQiReleasePercentage() {
        if (douqi_release_percentage == 0.0)
            return;
        douqi_release_percentage -= 0.01;
        if (douqi_release_percentage < 0.0)
            douqi_release_percentage = 0.0;
    }

    @Override
    public double getDouQiReleasePercentage() {
        return douqi_release_percentage;
    }

    @Override
    public void setDouQiReleasePercentage(double num) {
        if (num > 1.0)
            douqi_release_percentage = 1.0;
        else if (num < 0.0)
            douqi_release_percentage = 0.0;
        else
            douqi_release_percentage = num;
    }

    @Override
    public double getDouQiReleasePercentageMax() {
        return douqi_release_percentage_max;
    }

    @Override
    public void setDouQiReleasePercentageMax(double num) {
        if (num > 1.0)
            douqi_release_percentage_max = 1.0;
        else if (num < 0.0)
            douqi_release_percentage_max = 0.0;
        else
            douqi_release_percentage_max = num;
    }

    @Override
    public byte getSoulPropertyMain() {
        return soul_property_main;
    }

    @Override
    public boolean[] getSoulProperty() {
        return soul_property;
    }

    @Override
    public void addSoul() {
        addSoul(soul_attraction_num, true);//三天完全恢复一个正常人
    }

    @Override
    public void addSoul(double num, boolean is_be_affect) {
        if (is_be_affect)
            if (gongfa_choose != -1)
                num = num > 0 ? (num * gongfas.get(gongfa_choose).gongfa_soul_speed) : (num / gongfas.get(gongfa_choose).gongfa_soul_speed);
        num = num + soul;
        if (num >= soul_max)
            soul = soul_max;//去除多余灵魂力
        else if (num < 0)
            soul = 0;
        else
            soul = num;
    }

    @Override
    public double getSoul() {
        return soul;
    }

    @Override
    public void setSoul(double num) {
        if (num < 0)
            soul = 0;
        else if (num > soul_max)
            soul = soul_max;
        else
            soul = num;
    }

    @Override
    public double getSoulAttractionNum() {
        return soul_attraction_num;
    }

    @Override
    public void addSoulMax(double num) {
        num = soul_max + num;
        if (num < 0)
            soul_max = 0;
        else
            soul_max = num;
    }

    @Override
    public double getSoulMax() {
        return soul_max;
    }

    @Override
    public void setSoulMax(double num) {
        if (num < 0)
            soul_max = 0;
        else
            soul_max = num;
    }

    @Override
    public boolean addFire(byte num) {
        if (num >= FIRE_MAX || fire[num])
            return false;
        return fire[num] = true;
    }

    @Override
    public boolean[] getFire() {
        return fire;
    }

    @Override
    public void setFire(boolean[] fire_array) {
        fire = fire_array;
    }

    @Override
    public byte getBody() {
        return body;
    }

    @Override
    public void setBody(byte num) {
        body = num;
    }

    @Override
    public byte getEye() {
        return eye;
    }

    @Override
    public void setEye(byte num) {
        eye = num;
    }

    @Override
    public void isToLevelBig(boolean is_to_level_up) {
        is_to_level_big = is_to_level_up;
    }

    @Override
    public boolean isToLevelBig() {
        return is_to_level_big;
    }

    @Override
    public void isToLevelMiddle(boolean is_to_level_up) {
        is_to_level_middle = is_to_level_up;
    }

    @Override
    public boolean isToLevelMiddle() {
        return is_to_level_middle;
    }

    @Override
    public void isToLevelSmall(boolean is_to_level_up) {
        is_to_level_small = is_to_level_up;
    }

    @Override
    public boolean isToLevelSmall() {
        return is_to_level_small;
    }

    @Override
    public void isFlying(boolean flag) {
        isFlying = flag;
    }

    @Override
    public boolean isFlying() {
        return isFlying;
    }

    @Override
    public double[] getWorldAttr() {
        return world_attr;
    }

    @Override
    public void setWorldAttr(double[] worldAttrArray) {
        world_attr = worldAttrArray;
    }

    @Override
    public boolean isScaningBlock() {
        return is_scaning_block;
    }

    @Override
    public void isScaningBlock(boolean flag) {
        is_scaning_block = flag;
    }

    @Override
    public void addGongFa(GongFa gong_fa) {
        gongfas.add(gong_fa);
    }

    @Override
    public ArrayList<GongFa> getGongFas() {
        return gongfas;
    }

    @Override
    public int getGongFaChoose() {
        return gongfa_choose;
    }

    @Override
    public void setGongFaChoose(int num) {
        gongfa_choose = num;
    }

    @Override
    public void addDouJi(DouJi dou_ji) {
        doujis.add(dou_ji);
    }

    @Override
    public ArrayList<DouJi> getDouJis() {
        return doujis;
    }

    @Override
    public int getDouJiGroupChoose() {
        return douji_group_choose;
    }

    @Override
    public void setDouJiGroupChoose(int num) {
        douji_group_choose = num;
    }

    @Override
    public int[] getDouJiGroup() {
        return douji_group;
    }

    @Override
    public void setDouJiGroup(int[] num) {
        douji_group = num;
    }

    @Override
    public CompoundNBT serializeNBT() {
        int i, j;
        CompoundNBT compoundNBT = new CompoundNBT();
        compoundNBT.putInt("VERSION", VERSION);
        compoundNBT.putInt("level_up_time", level_up_time);
        compoundNBT.putDouble("douqi_have", douqi_have);
        compoundNBT.putDouble("douqi_have_max", douqi_have_max);
        compoundNBT.putDouble("douqi_have_max_level_up", douqi_have_max_level_up);
        compoundNBT.putInt("level_big", level_big);
        compoundNBT.putInt("level_middle", level_middle);
        compoundNBT.putInt("level_small", level_small);
        compoundNBT.putIntArray("level_all", level_all);
        compoundNBT.putDouble("douqi_compress", douqi_compress);
        compoundNBT.putDouble("douqi_compress_all", douqi_compress_all);
        compoundNBT.putDouble("douqi_compress_should_all", douqi_compress_should_all);
        compoundNBT.putDouble("douqi_min_compress", douqi_min_compress);
        compoundNBT.putDouble("douqi_compress_attraction", douqi_compress_attraction);
        compoundNBT.putDouble("douqi_attraction", douqi_attraction);
        compoundNBT.putDouble("douqi_level_up_pay", douqi_level_up_pay);
        compoundNBT.putDouble("douqi_release_percentage", douqi_release_percentage);
        compoundNBT.putDouble("douqi_release_percentage_max", douqi_release_percentage_max);
        compoundNBT.putInt("soul_property_main", soul_property_main);
        for (i = 0; i < SOUL_MAX; ++i)
            compoundNBT.putBoolean("soul_property_" + i, soul_property[i]);
        compoundNBT.putDouble("soul", soul);
        compoundNBT.putDouble("soul_attraction_num", soul_attraction_num);
        compoundNBT.putDouble("soul_max", soul_max);
        for (i = 0; i < FIRE_MAX; ++i)
            compoundNBT.putBoolean("fire_" + i, fire[i]);
        compoundNBT.putByte("body", body);
        compoundNBT.putByte("eye", eye);
        compoundNBT.putBoolean("is_to_level_big", is_to_level_big);
        compoundNBT.putBoolean("is_to_level_middle", is_to_level_middle);
        compoundNBT.putBoolean("is_to_level_small", is_to_level_small);
        compoundNBT.putBoolean("isFlying", isFlying);
        for (i = 0; i < SOUL_MAX; ++i) {
            compoundNBT.putDouble("world_attr_" + i, world_attr[i]);
            compoundNBT.putDouble("world_attr_from_block_th_" + i, world_attr_from_block_th[i]);
        }
        compoundNBT.putBoolean("is_scaning_block", is_scaning_block);
        i = 0;
        compoundNBT.putInt("gongfa_num", gongfas.size());
        for (GongFa gong_fa : gongfas) {
            compoundNBT.putString("gongfa_name" + i, gong_fa.gongfa_name);
            compoundNBT.putInt("gongfa_icon" + i, gong_fa.gongfa_icon);
            compoundNBT.putInt("gongfa_level_big" + i, gong_fa.gongfa_level_big);
            compoundNBT.putInt("gongfa_level_middle" + i, gong_fa.gongfa_level_middle);
            compoundNBT.putDouble("gongfa_douqi_speed" + i, gong_fa.gongfa_douqi_speed);
            compoundNBT.putDouble("gongfa_compress_speed" + i, gong_fa.gongfa_compress_speed);
            compoundNBT.putDouble("gongfa_soul_speed" + i, gong_fa.gongfa_soul_speed);
            compoundNBT.putInt("gongfa_property" + i, gong_fa.gongfa_property);
            compoundNBT.putDouble("gongfa_attack_num" + i, gong_fa.gongfa_attack_num);
            compoundNBT.putDouble("gongfa_defense_num" + i, gong_fa.gongfa_defense_num);
            compoundNBT.putDouble("gongfa_recover_num" + i, gong_fa.gongfa_recover_num);
            ++i;
        }
        compoundNBT.putInt("gongfa_choose", gongfa_choose);
        compoundNBT.putInt("douji_num", doujis.size());
        i = 0;
        for (DouJi dou_ji : doujis) {
            compoundNBT.putString("douji_name" + i, dou_ji.douji_name);
            compoundNBT.putInt("douji_icon" + i, dou_ji.douji_icon);
            compoundNBT.putInt("douji_level_big" + i, dou_ji.douji_level_big);
            compoundNBT.putInt("douji_level_middle" + i, dou_ji.douji_level_middle);
            compoundNBT.putInt("douji_keep_time" + i, dou_ji.douji_keep_time);
            compoundNBT.putInt("douji_property" + i, dou_ji.douji_property);
            compoundNBT.putDouble("douji_attack_num" + i, dou_ji.douji_attack_num);
            compoundNBT.putDouble("douji_defense_num" + i, dou_ji.douji_defense_num);
            compoundNBT.putDouble("douji_recover_num" + i, dou_ji.douji_recover_num);
            compoundNBT.putInt("douji_use_num" + i, dou_ji.douji_use_num);
            compoundNBT.putInt("douji_use_rebirth_time" + i, dou_ji.douji_use_rebirth_time);
            compoundNBT.putInt("douji_type" + i, dou_ji.douji_type);
            compoundNBT.putBoolean("is_have_entiy_modle" + i, dou_ji.is_have_entiy_modle);
            compoundNBT.putInt("points" + i, dou_ji.points);
            compoundNBT.putInt("rebirth_time" + i, dou_ji.rebirth_time);
            compoundNBT.putInt("use_time" + i, dou_ji.use_time);
            compoundNBT.putBoolean("is_ex_to_pay" + i, dou_ji.is_ex_to_pay);
            compoundNBT.putDouble("douqi_be_use" + i, dou_ji.douqi_be_use);
            ++i;
        }
        compoundNBT.putInt("douji_group_choose", douji_group_choose);
        compoundNBT.putIntArray("douji_group", douji_group);
        compoundNBT.putDouble("attack_num", attack_num);
        compoundNBT.putDouble("defense_num", defense_num);
        compoundNBT.putDouble("recover_num", recover_num);

        return compoundNBT;
    }

//    @Override
//    public double getAttackNum() {
//        if (gongfa_choose != -1)
//            return attack_num+gongfas.get(gongfa_choose).gongfa_attack_num+doujis.get(0).douji_attack_num;
//        else
//            return attack_num;
//    }
//
//    @Override
//    public double getDefenseNum() {
//        if (gongfa_choose != -1)
//            return defense_num+gongfas.get(gongfa_choose).gongfa_defense_num;
//        else
//            return defense_num;
//    }
//
//    @Override
//    public double getRecoverNum() {
//        if (gongfa_choose != -1)
//            return recover_num+gongfas.get(gongfa_choose).gongfa_recover_num;
//        else
//            return recover_num;
//    }

    @Override
    public void deserializeNBT(CompoundNBT nbt) {
        int i, j;
        int player_version = 0;
        try {
            player_version = nbt.getInt("VERSION");
        } catch (NullPointerException e) {
        }
        level_up_time = nbt.getInt("level_up_time");
        douqi_have = nbt.getDouble("douqi_have");
        douqi_have_max = nbt.getDouble("douqi_have_max");
        douqi_have_max_level_up = nbt.getDouble("douqi_have_max_level_up");
        level_big = nbt.getByte("level_big");
        level_middle = nbt.getByte("level_middle");
        level_small = nbt.getByte("level_small");
        level_all = nbt.getIntArray("level_all");
        douqi_compress = nbt.getDouble("douqi_compress");
        douqi_compress_all = nbt.getDouble("douqi_compress_all");
        douqi_compress_should_all = nbt.getDouble("douqi_compress_should_all");
        douqi_min_compress = nbt.getDouble("douqi_min_compress");
        douqi_compress_attraction = nbt.getDouble("douqi_compress_attraction");
        douqi_attraction = nbt.getDouble("douqi_attraction");
        douqi_level_up_pay = nbt.getDouble("douqi_level_up_pay");
        douqi_release_percentage = nbt.getDouble("douqi_release_percentage");
        douqi_release_percentage_max = nbt.getDouble("douqi_release_percentage_max");
        soul_property_main = nbt.getByte("soul_property_main");
        for (i = 0; i < SOUL_MAX; ++i)
            soul_property[i] = nbt.getBoolean("soul_property_" + i);
        soul = nbt.getDouble("soul");
        soul_attraction_num = nbt.getDouble("soul_attraction_num");
        soul_max = nbt.getDouble("soul_max");
        for (i = 0; i < SOUL_MAX; ++i)
            fire[i] = nbt.getBoolean("fire_" + i);
        body = nbt.getByte("body");
        eye = nbt.getByte("eye");
        is_to_level_big = nbt.getBoolean("is_to_level_big");
        is_to_level_middle = nbt.getBoolean("is_to_level_middle");
        is_to_level_small = nbt.getBoolean("is_to_level_small");
        isFlying = nbt.getBoolean("isFlying");
        for (i = 0; i < SOUL_MAX; ++i) {
            world_attr[i] = nbt.getDouble("world_attr_" + i);
            world_attr_from_block_th[i] = nbt.getDouble("world_attr_from_block_th_" + i);
        }
        is_scaning_block = nbt.getBoolean("is_scaning_block");
        int nbt_num;
        nbt_num = nbt.getInt("gongfa_num");
        GongFa gong_fa;
        if (nbt_num != gongfas.size()) {//删除原来的，然后重新增加:不需要更新
            gongfas.clear();
            for (i = 0; i < nbt_num; ++i) {
                gong_fa = new GongFa();
                gong_fa.gongfa_name = nbt.getString("gongfa_name" + i);
                gong_fa.gongfa_icon = nbt.getInt("gongfa_icon" + i);
                gong_fa.gongfa_level_big = nbt.getInt("gongfa_level_big" + i);
                gong_fa.gongfa_level_middle = nbt.getInt("gongfa_level_middle" + i);
                gong_fa.gongfa_douqi_speed = nbt.getDouble("gongfa_douqi_speed" + i);
                gong_fa.gongfa_compress_speed = nbt.getDouble("gongfa_compress_speed" + i);
                gong_fa.gongfa_soul_speed = nbt.getDouble("gongfa_soul_speed" + i);
                gong_fa.gongfa_property = nbt.getInt("gongfa_property" + i);
                gong_fa.gongfa_attack_num = nbt.getDouble("gongfa_attack_num" + i);
                gong_fa.gongfa_defense_num = nbt.getDouble("gongfa_defense_num" + i);
                gong_fa.gongfa_recover_num = nbt.getDouble("gongfa_recover_num" + i);
                gongfas.add(gong_fa);
            }
        }
        gongfa_choose = nbt.getInt("gongfa_choose");
        nbt_num = nbt.getInt("douji_num");
        DouJi dou_ji;
        if (nbt_num != doujis.size()) {//删除原来的，然后重新增加
            doujis.clear();
            for (i = 0; i < nbt_num; ++i) {
                dou_ji = null;
                dou_ji = DouJi.getDouJi(nbt.getString("douji_name" + i));
                dou_ji.douji_name = nbt.getString("douji_name" + i);
                dou_ji.douji_icon = nbt.getInt("douji_icon" + i);
                dou_ji.douji_level_big = nbt.getInt("douji_level_big" + i);
                dou_ji.douji_level_middle = nbt.getInt("douji_level_middle" + i);
                dou_ji.douji_keep_time = nbt.getInt("douji_keep_time" + i);
                dou_ji.douji_property = nbt.getInt("douji_property" + i);
                dou_ji.douji_attack_num = nbt.getDouble("douji_attack_num" + i);
                dou_ji.douji_defense_num = nbt.getDouble("douji_defense_num" + i);
                dou_ji.douji_recover_num = nbt.getDouble("douji_recover_num" + i);
                dou_ji.douji_use_num = nbt.getInt("douji_use_num" + i);
                dou_ji.douji_use_rebirth_time = nbt.getInt("douji_use_rebirth_time" + i);
                dou_ji.douji_type = nbt.getInt("douji_type" + i);
                dou_ji.is_have_entiy_modle = nbt.getBoolean("is_have_entiy_modle" + i);
                dou_ji.points = nbt.getInt("points" + i);
                dou_ji.rebirth_time = nbt.getInt("rebirth_time" + i);
                dou_ji.use_time = nbt.getInt("use_time" + i);
                dou_ji.is_ex_to_pay = nbt.getBoolean("is_ex_to_pay" + i);
                dou_ji.douqi_be_use = nbt.getDouble("douqi_be_use" + i);
                doujis.add(dou_ji);//自带douji_num+1
            }
        } else {//更新
            for (i = 0; i < doujis.size(); ++i) {
                dou_ji = doujis.get(i);
                dou_ji.points = nbt.getInt("points" + i);
                dou_ji.rebirth_time = nbt.getInt("rebirth_time" + i);
                dou_ji.use_time = nbt.getInt("use_time" + i);
            }
        }
        douji_group_choose = nbt.getInt("douji_group_choose");
        douji_group = nbt.getIntArray("douji_group");

        attack_num = nbt.getDouble("attack_num");
        defense_num = nbt.getDouble("defense_num");
        recover_num = nbt.getDouble("recover_num");
        nbt_num = nbt.getInt("effect_attack_num");
        if (player_version != VERSION)
            playerUpdate(player_version);
    }

    /**
     * 扫描用线程
     */
    private class Scan_Thread extends Thread {
        PlayerEntity player;
        World world;

        public Scan_Thread(PlayerEntity player, World world) {
            super();
            this.player = player;
            this.world = world;
        }

        @Override
        public void run() {
            //如果附近有...
            for (int i = -SCAN_BLOCK_R; i <= SCAN_BLOCK_R; ++i) {
                for (int j = -SCAN_BLOCK_R; j <= SCAN_BLOCK_R; ++j) {
                    for (int k = -SCAN_BLOCK_R; k <= SCAN_BLOCK_R; ++k) {
                        Block block = world.getBlockState(new BlockPos(player.getPosX(), player.getPosY(), player.getPosZ())).getBlock();
                        if (Tags.Blocks.COBBLESTONE.contains(block)) {//圆石
                            world_attr_from_block_th[7] += 0.0005;
                        }
                        if (Tags.Blocks.END_STONES.contains(block)) {//末地石
                            world_attr_from_block_th[10] += 0.0006;
                        }
                        if (Tags.Blocks.GLASS.contains(block)) {//草
                            world_attr_from_block_th[3] += 0.0005;
                        }
                        if (Tags.Blocks.GRAVEL.contains(block)) {//沙砾
                            world_attr_from_block_th[7] += 0.0004;
                            world_attr_from_block_th[8] += 0.0005;
                        }
                        if (Tags.Blocks.NETHERRACK.contains(block)) {//地狱岩
                            world_attr_from_block_th[1] += 0.0006;
                            world_attr_from_block_th[4] -= 0.0002;
                            world_attr_from_block_th[5] -= 0.0002;
                        }
                        if (Tags.Blocks.OBSIDIAN.contains(block)) {//黑曜石
                            world_attr_from_block_th[10] += 0.0006;
                        }
                        if (Tags.Blocks.ORES.contains(block)) {//矿石
                            world_attr_from_block_th[6] += 0.0006;
                        }
                        if (Tags.Blocks.SAND.contains(block)) {//沙子
                            world_attr_from_block_th[8] += 0.0006;
                            world_attr_from_block_th[4] -= 0.0002;
                            world_attr_from_block_th[5] -= 0.0002;
                        }
                        if (Tags.Blocks.SANDSTONE.contains(block)) {//沙石
                            world_attr_from_block_th[7] += 0.0005;
                            world_attr_from_block_th[8] += 0.0004;
                        }
                        if (Tags.Blocks.STONE.contains(block)) {//石头
                            world_attr_from_block_th[7] += 0.0006;
                        }
                        if (Tags.Blocks.STORAGE_BLOCKS.contains(block)) {//钻石块之类的
                            world_attr_from_block_th[7] += 0.0007;
                        }
                        if (Tags.Blocks.DIRT.contains(block)) {//土类
                            world_attr_from_block_th[6] += 0.0006;
                        }
                        if (BlockTags.PLANKS.contains(block)) {//木板
                            world_attr_from_block_th[3] += 0.0004;
                        }
                        if (BlockTags.SAPLINGS.contains(block)) {//树苗
                            world_attr_from_block_th[3] += 0.0005;
                        }
                        if (BlockTags.LOGS.contains(block)) {//原木
                            world_attr_from_block_th[3] += 0.0006;
                        }
                        if (BlockTags.SAND.contains(block)) {//沙子
                            world_attr_from_block_th[8] += 0.0006;
                            world_attr_from_block_th[4] -= 0.0002;
                            world_attr_from_block_th[5] -= 0.0002;
                        }
                        if (BlockTags.LEAVES.contains(block)) {//树叶
                            world_attr_from_block_th[3] += 0.0005;
                        }
                        if (BlockTags.ICE.contains(block)) {//雪
                            world_attr_from_block_th[4] += 0.0005;
                            world_attr_from_block_th[5] += 0.0005;
                            world_attr_from_block_th[1] -= 0.0002;
                        }
                        if (BlockTags.CROPS.contains(block)) {//农作物
                            world_attr_from_block_th[3] += 0.0005;
                        }
                        if (BlockTags.FIRE.contains(block)) {//火
                            world_attr_from_block_th[1] += 0.0006;
                            world_attr_from_block_th[4] -= 0.0002;
                            world_attr_from_block_th[5] -= 0.0002;
                        }
                        if (BlockTags.CAMPFIRES.contains(block)) {//营火
                            world_attr_from_block_th[1] += 0.0005;
                            world_attr_from_block_th[4] -= 0.0002;
                            world_attr_from_block_th[5] -= 0.0002;
                        }
                        if (BlockTags.BASE_STONE_OVERWORLD.contains(block)) {//末地方块
                            world_attr_from_block_th[10] += 0.0006;
                        }
                        if (BlockTags.BASE_STONE_NETHER.contains(block)) {//下界方块
                            world_attr_from_block_th[1] += 0.0006;
                            world_attr_from_block_th[10] += 0.0005;
                        }
                        if (Fluids.LAVA.getDefaultState().getBlockState().matchesBlock(block)) {//岩浆
                            world_attr_from_block_th[1] += 0.0006;
                            world_attr_from_block_th[9] += 0.0004;
                            world_attr_from_block_th[10] += 0.0004;
                            world_attr_from_block_th[4] -= 0.0006;
                            world_attr_from_block_th[5] -= 0.0006;
                        }
                        if (Fluids.WATER.getDefaultState().getBlockState().matchesBlock(block)) {//水
                            world_attr_from_block_th[1] -= 0.0006;
                            world_attr_from_block_th[4] += 0.0006;
                            world_attr_from_block_th[5] += 0.0006;
                        }
                        if (FluidsRegistry.zhu_ji_ling_ye_fluid.get().getDefaultState().getBlockState().matchesBlock(block)) {//筑基灵液
                            for (int num = 0; num < world_attr_from_block_th.length; ++num)
                                world_attr_from_block_th[num] += 0.0006;
                        }
                    }
                }
            }
            BlockState blockState = world.getBlockState(new BlockPos(player.getPosX(), player.getPosY(), player.getPosZ()));
            //如果泡筑基灵液
            if (FluidsRegistry.zhu_ji_ling_ye_fluid.get().getDefaultState().getBlockState().matchesBlock(blockState.getBlock()
            )) {
                for (int world_attr_from_block_th_num = 0; world_attr_from_block_th_num < world_attr_from_block_th.length; ++world_attr_from_block_th_num) {
                    world_attr_from_block_th[world_attr_from_block_th_num] += 0.5;
                }
                is_scaning_block = false;
            }
        }
    }
}